package com.spyx.cart.service.impl;

import com.atyx.spyx.enums.SkuType;
import com.atyx.spyx.model.order.CartInfo;
import com.atyx.spyx.model.product.SkuInfo;
import com.spyx.cart.service.CartService;
import com.spyx.constant.RedisConst;
import com.spyx.exception.SpyxException;
import com.spyx.product.ProductClient;
import com.spyx.result.ResultCodeEnum;
import io.jsonwebtoken.lang.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductClient productClient;

    private String getCartKey(Long userId) {
        //定义key user:userId:cart
        // user:101:cart  user:102:cart
        //user:101:order  user:102:order
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
    //  设置key 的过期时间！
    private void setCartKeyExpire(String cartKey) {
        redisTemplate.expire(cartKey, RedisConst.USER_CART_EXPIRE, TimeUnit.SECONDS);
    }

    @Override
    public void addtoCart(Long skuid, Long skuNum, Long userId) {
        //1.先从redis中获取购物车
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //2.判断被添加的商品是否在购物车中
        CartInfo cartInfo =null;
        if(hashOps.hasKey(skuid.toString())){
            //2.1 商品已经存在于购物车
            //先取出商品
            cartInfo = hashOps.get(skuid.toString());
            int nowskunum=cartInfo.getSkuNum()+skuNum.intValue() ;//当前购买数量
            if(nowskunum<1){  //校验购买的数量是否合理
                return;
            }
            //判断购买数量是否超过限购数量
            if(nowskunum>cartInfo.getPerLimit()){
                throw new SpyxException(ResultCodeEnum.SKU_LIMIT_ERROR);
            }
            cartInfo.setSkuNum(nowskunum);//设置购买的数量
            cartInfo.setCurrentBuyNum(nowskunum);//当天已购买个数

            cartInfo.setIsChecked(1);//是否被选中
            cartInfo.setUpdateTime(new Date());//设置更新时间
        }else{
            skuNum=1L;
            //2.2 商品不存在于购物车
             cartInfo = new CartInfo();
            //填充cartInfo中的数据-远程调取根据skuid,查询skuInfo的方法
            SkuInfo skuInfo = productClient.findById(skuid);
            if(skuInfo==null){
                throw  new SpyxException(ResultCodeEnum.DATA_ERROR);
            }
            cartInfo.setSkuId(skuid);
            cartInfo.setCategoryId(skuInfo.getCategoryId());
            cartInfo.setSkuType(skuInfo.getSkuType());
            cartInfo.setIsNewPerson(skuInfo.getIsNewPerson());
            cartInfo.setUserId(userId);
            cartInfo.setCartPrice(skuInfo.getPrice());
            cartInfo.setSkuNum(skuNum.intValue());
            cartInfo.setCurrentBuyNum(skuNum.intValue());
            cartInfo.setSkuType(SkuType.COMMON.getCode());
            cartInfo.setPerLimit(skuInfo.getPerLimit());//限购
            cartInfo.setImgUrl(skuInfo.getImgUrl());
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setWareId(skuInfo.getWareId());
            cartInfo.setIsChecked(1); //是否被选中
            cartInfo.setStatus(1);//数据状态
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
        }
        //3.将商品添加到redis中
        hashOps.put(skuid.toString(),cartInfo);
        //设置cartKey的有效时间
        this.setCartKeyExpire(cartKey);
    }

    @Override
    public void deleteByskuId(Long skuid, Long userId) {
        //1.先从redis中获取购物车中的数据
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //2.判断被删除的skuid是否存在于购物车
        if(hashOps.hasKey(skuid.toString())){
            hashOps.delete(skuid.toString());
        }
    }

    @Override
    public void deleteByskuIds(Long userId, List<Long> skuids) {
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //遍历skuids，取出每一个id值，再删除
        for (Long skuid : skuids) {
            if(hashOps.hasKey(skuid.toString())){
                hashOps.delete(skuid.toString());
            }
        }
    }

    @Override
    public void clearCart(Long userId) {
        //1.获取购物车中数据
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //2.获取购物车中商品的信息
        List<CartInfo> cartInfoList = hashOps.values();
        //3.删除每件商品
        for (CartInfo cartInfo : cartInfoList) {
            hashOps.delete(cartInfo.getSkuId().toString());
        }
    }

    @Override
    public List<CartInfo> getCartList(Long userId) {

        if(StringUtils.isEmpty(userId)){
            System.out.println("userid为空");
            return null;
        }
        //1.从redis中获取购物车对象
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        //2.获取购物车中的数据
        List<CartInfo> cartInfoList = hashOps.values();
        //3.校验购物车中是否有数据，有的话，再对商品进行排序(根据创建时间排序)
        if(!Collections.isEmpty(cartInfoList)){
            cartInfoList.sort(new Comparator<CartInfo>() {
                @Override
                public int compare(CartInfo o1, CartInfo o2) {
                    return o1.getCreateTime().compareTo(o2.getCreateTime());
                }
            });
        }
        return cartInfoList;
    }

    @Override
    public void checkCart(Long skuId, Long isChecked, Long userId) {
        //1.先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //2.从redis中获取购物车的商品列表
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //3.根据skuid,查找商品信息
        CartInfo cartInfo = hashOps.get(skuId.toString());
        //4.更新状态
        if(cartInfo!=null){
            cartInfo.setIsChecked(isChecked.intValue());
            hashOps.put(skuId.toString(),cartInfo);//存储数据到redis中
            this.setCartKeyExpire(cartKey);  //设置购物车的有效期
        }
    }
    @Override
    public void checkAllCart(Long userId, Integer isChecked) {
        //1.先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //2.从redis中获取购物车的商品列表
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //3.获取redis中购物车的商品列表
        List<CartInfo> cartInfoList = hashOps.values();
        //4.更新状态
        for (CartInfo cartInfo : cartInfoList) {
            cartInfo.setIsChecked(isChecked.intValue());
            hashOps.put(cartInfo.getSkuId().toString(),cartInfo);//存储数据到redis中
        }
        //5.设置购物车的有效期
        this.setCartKeyExpire(cartKey);

    }

    @Override
    public void batchCheckCart(List<Long> skuIdList, Long userId, Integer isChecked) {
        //1.先获取购物车的key
        String cartKey = this.getCartKey(userId);
        //2.从redis中获取购物车的商品列表
        BoundHashOperations<String,String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //3.更新指定的sku商品
        for (Long skuid : skuIdList) {
            CartInfo cartInfo = hashOps.get(skuid.toString());
            //4.更新状态
            if(cartInfo!=null){
                cartInfo.setIsChecked(isChecked.intValue());
                hashOps.put(skuid.toString(),cartInfo);//存储数据到redis中
            }
        }
        //4,设置购物车的有效期
        this.setCartKeyExpire(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //如何筛选出购物车中哪些商品是被选中的
        //1.获取redis中购物车的列表
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
        //2.从购物车列表中获取被选中的商品，并封装到一个集合中
      /*  List<CartInfo> cartCheckedInfoList=new ArrayList<>();
        List<CartInfo> cartInfoList = hashOps.values();
        for (CartInfo cartInfo : cartInfoList) {
            if(cartInfo.getIsChecked().intValue()==1){
                cartCheckedInfoList.add(cartInfo);
            }
        }*/
        //使用stream 筛选
        List<CartInfo> cartCheckedInfoList=
                hashOps.values().stream()
                        .filter(cartInfo -> cartInfo.getIsChecked().intValue()==1)
                        .collect(Collectors.toList());
        return cartCheckedInfoList;
    }

    @Override  //根据用户iD,删除购物车中已下单的商品信息
    public void deleteCart(Long userId) {
        //复习: redis中存储购物车商品数据: key=user:userid:cart  field=skuid   value=skuinfo
        //1.根据用户iD,获取购物车中选中的商品信息
        List<CartInfo> cartCheckedList = this.getCartCheckedList(userId);
        //2.筛选出被选中商品的iD值
        List<Long> skuIdList =
                cartCheckedList.stream()
                        .map(cartInfo -> cartInfo.getSkuId()).collect(Collectors.toList());
        //3.从redis中获取数据
        String cartKey = this.getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> ops = redisTemplate.boundHashOps(cartKey);
        //4.遍历skuidList，将对应的skuid从redis中删除
        for (Long skuid : skuIdList) {
            ops.delete(skuid.toString());
        }
    }
}
